home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / bsrc_p2.arc / ZMISC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-30  |  23.3 KB  |  689 lines

  1. /*--------------------------------------------------------------------------*/
  2. /* FILE: zmisc.c    (Opus zmodem routines used by send and receive)         */
  3. /*                                                                          */
  4. /*                                                                          */
  5. /*               The Opus Computer-Based Conversation System                */
  6. /*       (c) Copyright 1986, Wynn Wagner III, All Rights Reserved           */
  7. /*                                                                          */
  8. /*      This implementation of Chuck Forsberg's ZMODEM protocol was         */
  9. /*              for Opus by Rick Huebner and Wynn Wagner III                */
  10. /*                                                                          */
  11. /* (MSC/4 with /Zp /Ox)                                                     */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*  This module is similar to a routine used by Opus-Cbcs (1.00).  It is    */
  17. /*  provided for your information only.  You will find routines that need   */
  18. /*  to be coded and identifiers to be resolved.                             */
  19. /*                                                                          */
  20. /*  There is absolutely no guarantee that anything here will work.  If you  */
  21. /*  break this routine, you own both pieces.                                */
  22. /*                                                                          */
  23. /*  USAGE:  You may use this material in any program with no obligation     */
  24. /*          as long as there is no charge for your program.  For more       */
  25. /*          information about commercial use, contact the "OPUSinfo HERE"   */
  26. /*          BBS (124/111).                                                  */
  27. /*                                                                          */
  28. /*  NOTE:   There are a couple of things the Opus implementation does that  */
  29. /*          aren't part of the original ZModem protocol.  They all deal     */
  30. /*          with WaZOO type ("ZedZap") netmail and should only show up when */
  31. /*          used under that condition.                                      */
  32. /*                                                                          */
  33. /*             * The maximum packet size can grow larger than 1k.  It is    */
  34. /*               sensitive to the baud rate.  (2400b=2048k; 9600b=8192k)    */
  35. /*             * The sender must be able to send nothing.  In other words,  */
  36. /*               the sending system must be able to initiate and terminate  */
  37. /*               a zmodem send session without having to actually send a    */
  38. /*               file.  Normally this kind of thing would never happen in   */
  39. /*               zmodem.                                                    */
  40. /*                                                                          */
  41. /*                                                                          */
  42. /*--------------------------------------------------------------------------*/
  43. #include "zmodem.h"
  44. #include "com.h"
  45.  
  46.  
  47. static int Rxtype;               /* Type of header received                 */
  48. static int Rxframeind;           /* ZBIN ZBIN32,ZHEX type of frame received */
  49.  
  50. static char hex[] = "0123456789abcdef";
  51.  
  52. /* Send a byte as two hex digits */
  53. #define Z_PUTHEX(i,c) {i=(c);SENDBYTE(hex[((i)&0xF0)>>4]);SENDBYTE(hex[(i)&0xF]);}
  54.  
  55.  
  56.  
  57. /*--------------------------------------------------------------------------*/
  58. /* Routines used by other ZModem modules...                                 */
  59. /*--------------------------------------------------------------------------*/
  60. int  pascal Z_GetByte(int);
  61. void pascal Z_PutString(unsigned char *);
  62. void pascal Z_SendHexHeader(unsigned short,unsigned char *);
  63. int  pascal Z_GetHeader(unsigned char *);
  64. int  pascal Z_GetZDL(void);
  65. void pascal Z_PutLongIntoHeader(long);
  66. #ifdef NO_CRC_ASM            /* If no assembler version */
  67. unsigned short pascal Z_UpdateCRC(unsigned short,unsigned short);
  68. #endif
  69.  
  70. /*--------------------------------------------------------------------------*/
  71. /* Private routines                                                         */
  72. /*--------------------------------------------------------------------------*/
  73. static int  pascal _Z_qk_read(void);
  74. static int  pascal _Z_GetBinaryHeader(unsigned char *);
  75. static int  pascal _Z_GetHexHeader(unsigned char *);
  76. static int  pascal _Z_GetHex(void);
  77. static int  pascal _Z_TimedRead(void);
  78. static long pascal _Z_PullLongFromHeader(unsigned char *);
  79.  
  80.  
  81.  
  82. extern byte *local_CEOL;
  83. extern char *KBD_msg;
  84.  
  85.  
  86. void pascal z_message( s )
  87.    byte *s;
  88.    begin
  89.        gotoxy( locate_x+20, locate_y );
  90.       if (s) cputs(s);
  91.       cputs( local_CEOL );
  92.    end
  93.  
  94.  
  95. void z_log(s)
  96.    byte *s;
  97.    begin
  98.       word x, y;
  99.  
  100.       z_message(s);
  101.  
  102.       x  = locate_x;
  103.       y  = locate_y;
  104.       status_line(s); /* also does disk file logging */
  105.       locate_x = x;
  106.       locate_y = y;
  107.  
  108.    end
  109.  
  110.  
  111. void show_loc(l,w)
  112.    unsigned long  l;
  113.    unsigned int   w;
  114.    begin
  115.       gotoxy( locate_x+35, locate_y );
  116.       cprintf("Ofs=%ld Retries=%d%s",l,w,local_CEOL);
  117.    end
  118.  
  119.  
  120. byte * pascal zalloc()
  121.    begin
  122.       byte *sptr,*malloc();
  123.  
  124.       sptr  = malloc(WAZOOMAX);
  125.       if (!sptr)
  126.          begin
  127.              status_line("!Z-MEMOVFL");
  128.             adios(2);
  129.          end
  130.       return sptr;
  131.    end
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139. /*--------------------------------------------------------------------------*/
  140. /* Z GET BYTE                                                               */
  141. /* Get a byte from the modem;                                               */
  142. /* return TIMEOUT if no read within timeout tenths,                         */
  143. /* return RCDO if carrier lost                                              */
  144. /*--------------------------------------------------------------------------*/
  145. int pascal Z_GetByte(tenths)
  146.    register int tenths;
  147.    begin
  148.       register int i;
  149.       long timeout, timerset();
  150.  
  151.       i^=i;
  152.       do
  153.           begin
  154.             if (CHAR_AVAIL()) return MODEM_IN();
  155.             time_release();
  156.          end
  157.       while((i++)<2000);
  158.  
  159.  
  160.       timeout = timerset(tenths * 10);
  161.  
  162.       while(!CHAR_AVAIL())
  163.          begin
  164.             if (!CARRIER)     return RCDO;
  165.  
  166.             time_release();
  167.             if (timeup(timeout)) return TIMEOUT;
  168.          end
  169.  
  170.       return MODEM_IN();
  171.  
  172.    end
  173.  
  174.  
  175.  
  176.  
  177.  
  178. /*--------------------------------------------------------------------------*/
  179. /* QK_READ  (like Z_GetByte, but assumes the time to be Rxtimeout)          */
  180. /* Get a byte from the modem;                                               */
  181. /* return TIMEOUT if no read within timeout tenths,                         */
  182. /* return RCDO if carrier lost                                              */
  183. /*--------------------------------------------------------------------------*/
  184. static int pascal _Z_qk_read()
  185.    begin
  186.       register int i;
  187.       register int time_val;
  188.       long timeout, timerset();
  189.  
  190.       time_val^=time_val;
  191.       do
  192.           begin
  193.             if (CHAR_AVAIL())  return MODEM_IN();
  194.             if (!(MODEM_STATUS()&ctl.carrier_mask))          return RCDO;
  195.             time_release();
  196.          end
  197.       while((time_val++)<2000);
  198.  
  199.       timeout = timerset(Rxtimeout*10);
  200.       do
  201.          begin
  202.             if (CHAR_AVAIL())  return MODEM_IN();
  203.             if (!(MODEM_STATUS()&ctl.carrier_mask))          return RCDO;
  204.             time_release();
  205.          end
  206.       while(!timeup(timeout));
  207.  
  208.       return TIMEOUT;
  209.  
  210.    end
  211.  
  212. /*--------------------------------------------------------------------------*/
  213. /* Z PUT STRING                                                             */
  214. /* Send a string to the modem, processing for \336 (sleep 1 sec)            */
  215. /* and \335 (break signal, ignored)                                         */
  216. /*--------------------------------------------------------------------------*/
  217. void pascal Z_PutString(s)
  218.    register unsigned char *s;
  219.    begin
  220.       register int c;
  221.  
  222.       while (*s)
  223.          begin
  224.             switch (c = *s++)
  225.                begin
  226.                   case '\336':   big_pause(2);
  227.                   case '\335':   break;
  228.                   default:       SENDBYTE(c);
  229.                end /* switch */
  230.  
  231.          end /* while */
  232.  
  233.    end /* Z_PutString */
  234.  
  235.  
  236. #ifdef NO_CRC_ASM            /* If no assembler version */
  237. /*--------------------------------------------------------------------------*/
  238. /* Z UPDATE CRC                                                             */
  239. /* update CRC                                                               */
  240. /*--------------------------------------------------------------------------*/
  241. unsigned short pascal Z_UpdateCRC(c, crc)
  242.    unsigned short c;
  243.    unsigned short crc;
  244.    begin
  245.       register int    count;
  246.       register word   temp;
  247.  
  248.       temp   = crc;
  249.  
  250.       for (count=8; --count>=0; )
  251.          begin
  252.             if (temp & 0x8000)
  253.                begin
  254.                   temp <<= 1;
  255.                   temp += (((c<<=1) & 0400)  !=  0);
  256.                   temp ^= 0x1021;
  257.                end
  258.             else
  259.                begin
  260.                   temp <<= 1;
  261.                   temp += (((c<<=1) & 0400)  !=  0);
  262.                end
  263.          end /* for */
  264.  
  265.       return temp;
  266.    end /* z_crc update */
  267. #endif                    /* NO_CRC_ASM */
  268.  
  269.  
  270.  
  271. /*--------------------------------------------------------------------------*/
  272. /* Z SEND HEX HEADER                                                        */
  273. /* Send ZMODEM HEX header hdr of type type                                  */
  274. /*--------------------------------------------------------------------------*/
  275. void pascal Z_SendHexHeader(type, hdr)
  276.    unsigned short type;
  277.    register unsigned char *hdr;
  278.    begin
  279.       register int   n;
  280.       register int   i;
  281.       register word  crc;
  282.  
  283.       SENDBYTE(ZPAD);
  284.       SENDBYTE(ZPAD);
  285.       SENDBYTE(ZDLE);
  286.       SENDBYTE(ZHEX);
  287.       Z_PUTHEX(i,type);
  288.  
  289.       crc = Z_UpdateCRC(type, 0);
  290.       for (n=4; --n >= 0;)
  291.          begin
  292.             Z_PUTHEX(i,(*hdr));
  293.             crc = Z_UpdateCRC(((unsigned short)(*hdr++)), crc);
  294.          end
  295. #ifdef NO_CRC_ASM
  296.       crc = Z_UpdateCRC(0,crc);
  297.       crc = Z_UpdateCRC(0,crc);
  298. #endif
  299.       Z_PUTHEX(i,(crc>>8));
  300.       Z_PUTHEX(i,crc);
  301.  
  302.       /* Make it printable on remote machine */
  303.       SENDBYTE('\r');
  304.       SENDBYTE('\n');
  305.  
  306.       /* Uncork the remote in case a fake XOFF has stopped data flow */
  307.       if (type != ZFIN && type != ZACK) SENDBYTE(021);
  308.  
  309.       while (CARRIER && !OUT_EMPTY())
  310.          time_release();
  311.       if (!CARRIER)
  312.          CLEAR_OUTBOUND();
  313.  
  314.    end /* Z_SendHexHeader */
  315.  
  316.  
  317.  
  318. /*--------------------------------------------------------------------------*/
  319. /* Z GET HEADER                                                             */
  320. /* Read a ZMODEM header to hdr, either binary or hex.                       */
  321. /*   On success, set Zmodem to 1 and return type of header.                 */
  322. /*   Otherwise return negative on error                                     */
  323. /*--------------------------------------------------------------------------*/
  324. int pascal Z_GetHeader(hdr)
  325.    byte *hdr;
  326.    begin
  327.  
  328.       register int   c;
  329.       register int   n;
  330.       int            cancount;
  331.  
  332.  
  333.       n        = cur_baud * 2;   /* Max characters before start of frame */
  334.       cancount = 5;
  335.  
  336. Again:
  337.  
  338.       if (((KEYPRESS()) and (READKB()==27)))
  339.          begin
  340.             send_can();
  341.             z_log( KBD_msg );
  342.             return ZCAN;
  343.          end
  344.  
  345.       Rxframeind = Rxtype = 0;
  346.  
  347.       switch (c = _Z_TimedRead())
  348.          begin
  349.  
  350.             case ZPAD:
  351.             case ZPAD|0200: /*-----------------------------------------------*/
  352.                            /* This is what we want.                         */
  353.                            /*-----------------------------------------------*/
  354.                            break;
  355.  
  356.             case RCDO:
  357.             case TIMEOUT:  /*-----------------------------------------------*/
  358.                            /*                                               */
  359.                            /*-----------------------------------------------*/
  360.                            goto Done;
  361.  
  362.             case CAN:      /*-----------------------------------------------*/
  363.                            /*                                               */
  364.                            /*-----------------------------------------------*/
  365. GotCan:                    if (--cancount <= 0)
  366.                               begin
  367.                                  c = ZCAN;
  368.                                  goto Done;
  369.                               end
  370.                            switch (c = Z_GetByte(1)) {
  371.                               case TIMEOUT: goto Again;
  372.  
  373.                               case ZCRCW:   c = ERROR;
  374.                                             /* fallthrough... */
  375.  
  376.                               case RCDO:    goto Done;
  377.  
  378.                               case CAN:     if (--cancount <= 0)
  379.                                                begin
  380.                                                   c = ZCAN;
  381.                                                   goto Done;
  382.                                                end
  383.                                             goto Again;
  384.                            }
  385.                            /* fallthrough... */
  386.  
  387.  
  388.             default:       /*-----------------------------------------------*/
  389.                            /*                                               */
  390.                            /*-----------------------------------------------*/
  391. Agn2:
  392.  
  393.                            if (--n <= 0)
  394.                               begin
  395.                                  z_log( FUBAR_msg );
  396.                                  return ERROR;
  397.                               end
  398.  
  399.                            if (c != CAN) cancount = 5;
  400.                            goto Again;
  401.  
  402.          end /* switch */
  403.  
  404.       cancount = 5;
  405.  
  406. Splat:
  407.  
  408.       switch (c = _Z_TimedRead())
  409.          begin
  410.             case ZDLE:     /*-----------------------------------------------*/
  411.                            /* This is what we want.                         */
  412.                            /*-----------------------------------------------*/
  413.                            break;
  414.  
  415.             case ZPAD:     /*-----------------------------------------------*/
  416.                            /*                                               */
  417.                            /*-----------------------------------------------*/
  418.                            goto Splat;
  419.  
  420.             case RCDO:
  421.             case TIMEOUT:  /*-----------------------------------------------*/
  422.                            /*                                               */
  423.                            /*-----------------------------------------------*/
  424.                            goto Done;
  425.  
  426.             default:       /*-----------------------------------------------*/
  427.                            /*                                               */
  428.                            /*-----------------------------------------------*/
  429.                            goto Agn2;
  430.  
  431.          end /* switch */
  432.  
  433.  
  434.       switch (c = _Z_TimedRead())
  435.          begin
  436.  
  437.             case ZBIN:     /*-----------------------------------------------*/
  438.                            /*                                               */
  439.                            /*-----------------------------------------------*/
  440.                            Rxframeind = ZBIN;
  441.                            c =  _Z_GetBinaryHeader(hdr);
  442.                            break;
  443.  
  444.             case ZHEX:     /*-----------------------------------------------*/
  445.                            /*                                               */
  446.                            /*-----------------------------------------------*/
  447.                            Rxframeind = ZHEX;
  448.                            c =  _Z_GetHexHeader(hdr);
  449.                            break;
  450.  
  451.             case CAN:      /*-----------------------------------------------*/
  452.                            /*                                               */
  453.                            /*-----------------------------------------------*/
  454.                            goto GotCan;
  455.  
  456.             case RCDO:
  457.             case TIMEOUT:  /*-----------------------------------------------*/
  458.                            /*                                               */
  459.                            /*-----------------------------------------------*/
  460.                            goto Done;
  461.  
  462.             default:       /*-----------------------------------------------*/
  463.                            /*                                               */
  464.                            /*-----------------------------------------------*/
  465.                            goto Agn2;
  466.  
  467.          end /* switch */
  468.  
  469.       Rxpos = _Z_PullLongFromHeader(hdr);
  470.  
  471. Done:
  472.  
  473.       return c;
  474.  
  475.    end /* Z_GetHeader */
  476.  
  477.  
  478.  
  479.  
  480.  
  481. /*--------------------------------------------------------------------------*/
  482. /* Z GET BINARY HEADER                                                      */
  483. /* Receive a binary style header (type and position)                        */
  484. /*--------------------------------------------------------------------------*/
  485. static int pascal _Z_GetBinaryHeader(hdr)
  486.    register byte *hdr;
  487.    begin
  488.       register int    c;
  489.       register word   crc;
  490.       register int    n;
  491.  
  492.       if ((c   = Z_GetZDL()) & ~0xFF)   return c;
  493.       Rxtype   = c;
  494.       crc      = Z_UpdateCRC(c, 0);
  495.  
  496.       for (n=4; --n >= 0;)
  497.          begin
  498.             if ((c = Z_GetZDL()) & ~0xFF) return c;
  499.             crc = Z_UpdateCRC(c, crc);
  500.             *hdr++ = c;
  501.          end
  502.       if ((c   = Z_GetZDL()) & ~0xFF) return c;
  503.  
  504.       crc      = Z_UpdateCRC(c, crc);
  505.       if ((c   = Z_GetZDL()) & ~0xFF) return c;
  506.  
  507.       crc = Z_UpdateCRC(c, crc);
  508.       if (crc & 0xFFFF)
  509.          begin
  510.             z_message( CRC_msg );
  511.             return ERROR;
  512.          end
  513.  
  514.       return Rxtype;
  515.  
  516.    end /* _Z_GetBinaryHeader */
  517.  
  518.  
  519.  
  520.  
  521. /*--------------------------------------------------------------------------*/
  522. /* Z GET HEX HEADER                                                         */
  523. /* Receive a hex style header (type and position)                           */
  524. /*--------------------------------------------------------------------------*/
  525. static int pascal _Z_GetHexHeader(hdr)
  526.    register unsigned char *hdr;
  527.    begin
  528.       register int   c;
  529.       register word  crc;
  530.       register int   n;
  531.  
  532.       if ((c   = _Z_GetHex()) < 0) return c;
  533.       Rxtype   = c;
  534.       crc      = Z_UpdateCRC(c, 0);
  535.  
  536.       for (n=4; --n >= 0;)
  537.          begin
  538.             if ((c = _Z_GetHex()) < 0) return c;
  539.             crc      = Z_UpdateCRC(c, crc);
  540.             *hdr++   = c;
  541.          end
  542.  
  543.       if ((c = _Z_GetHex()) < 0) return c;
  544.       crc = Z_UpdateCRC(c, crc);
  545.       if ((c = _Z_GetHex()) < 0) return c;
  546.       crc = Z_UpdateCRC(c, crc);
  547.       if (crc & 0xFFFF)
  548.          begin
  549.             z_message( CRC_msg );
  550.             return ERROR;
  551.          end
  552.       if (Z_GetByte(1) == '\r') Z_GetByte(1);  /* Throw away possible cr/lf */
  553.  
  554.       return Rxtype;
  555.  
  556.    end
  557.  
  558.  
  559.  
  560.  
  561.  
  562. /*--------------------------------------------------------------------------*/
  563. /* Z GET HEX                                                                */
  564. /* Decode two lower case hex digits into an 8 bit byte value                */
  565. /*--------------------------------------------------------------------------*/
  566. static int pascal _Z_GetHex()
  567.    begin
  568.       register int c, n;
  569.  
  570.       if ((n = _Z_TimedRead()) < 0) return n;
  571.       n -= '0';
  572.       if (n > 9) n -= ('a' - ':');
  573.       if (n & ~0xF) return ERROR;
  574.  
  575.       if ((c = _Z_TimedRead()) < 0) return c;
  576.       c -= '0';
  577.       if (c > 9) c -= ('a' - ':');
  578.       if (c & ~0xF) return ERROR;
  579.  
  580.       return (n<<4 | c);
  581.    end
  582.  
  583.  
  584.  
  585.  
  586. /*--------------------------------------------------------------------------*/
  587. /* Z GET ZDL                                                                */
  588. /* Read a byte, checking for ZMODEM escape encoding                         */
  589. /* including CAN*5 which represents a quick abort                           */
  590. /*--------------------------------------------------------------------------*/
  591. int pascal Z_GetZDL()
  592.    begin
  593.       register int c;
  594.  
  595.       if (!CARRIER)
  596.          return RCDO;
  597.       if ((c = _Z_qk_read()) != ZDLE)
  598.          return c;
  599.  
  600.       switch (c=_Z_qk_read())
  601.          begin
  602.             case CAN:   return ((c=_Z_qk_read())<0)?               c :
  603.                                ((c==CAN) && ((c=_Z_qk_read())<0))? c :
  604.                                ((c==CAN) && ((c=_Z_qk_read())<0))? c : (GOTCAN);
  605.  
  606.             case ZCRCE:
  607.             case ZCRCG:
  608.             case ZCRCQ:
  609.             case ZCRCW: return (c | GOTOR);
  610.  
  611.             case ZRUB0: return 0x7F;
  612.  
  613.             case ZRUB1: return 0xFF;
  614.  
  615.             default:    return   (c<0)?            c :
  616.                                  ((c&0x60)==0x40)? (c ^ 0x40)  : ERROR;
  617.  
  618.          end /* switch */
  619.  
  620.    end /* Z_GetZDL */
  621.  
  622.  
  623.  
  624.  
  625.  
  626. /*--------------------------------------------------------------------------*/
  627. /* Z TIMED READ                                                             */
  628. /* Read a character from the modem line with timeout.                       */
  629. /*  Eat parity, XON and XOFF characters.                                    */
  630. /*--------------------------------------------------------------------------*/
  631. static int pascal _Z_TimedRead()
  632.    begin
  633.       register int c;
  634.  
  635.       for (;;)
  636.          begin
  637.             if ((c = _Z_qk_read()) < 0) return c;
  638.  
  639.             switch (c &= 0x7F)
  640.                begin
  641.                   case XON:
  642.                   case XOFF:  continue;
  643.  
  644.                   default:    return c;
  645.                end /* switch */
  646.  
  647.          end /* for */
  648.  
  649.    end /* _Z_TimedRead */
  650.  
  651.  
  652.  
  653.  
  654. /*--------------------------------------------------------------------------*/
  655. /* Z LONG TO HEADER                                                         */
  656. /* Store long integer pos in Txhdr                                          */
  657. /*--------------------------------------------------------------------------*/
  658. void pascal Z_PutLongIntoHeader(pos)
  659.    long pos;
  660.    begin
  661.       Txhdr[ZP0] = pos;
  662.       Txhdr[ZP1] = pos>>8;
  663.       Txhdr[ZP2] = pos>>16;
  664.       Txhdr[ZP3] = pos>>24;
  665.    end /* Z_PutLongIntoHeader */
  666.  
  667.  
  668.  
  669.  
  670. /*--------------------------------------------------------------------------*/
  671. /* Z PULL LONG FROM HEADER                                                  */
  672. /* Recover a long integer from a header                                     */
  673. /*--------------------------------------------------------------------------*/
  674. static long pascal _Z_PullLongFromHeader(hdr)
  675.    unsigned char *hdr;
  676.    begin
  677.       long l;
  678.  
  679.       l = hdr[ZP3];
  680.       l = (l << 8) | hdr[ZP2];
  681.       l = (l << 8) | hdr[ZP1];
  682.       l = (l << 8) | hdr[ZP0];
  683.       return l;
  684.    end /* _Z_PullLongFromHeader */
  685.  
  686.  
  687. /* END OF FILE: zmisc.c */
  688.  
  689.